package org.hefan.hrm.service.impl;

import org.apache.commons.lang.StringUtils;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.aggregations.AggregationBuilders;
import org.elasticsearch.search.aggregations.bucket.terms.StringTerms;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.sort.SortBuilders;
import org.elasticsearch.search.sort.SortOrder;
import org.hefan.hrm.config.HighlightResultMapper;
import org.hefan.hrm.doc.CourseDoc;
import org.hefan.hrm.query.CourseDocQuery;
import org.hefan.hrm.repository.CourseDocRepository;
import org.hefan.hrm.service.ICourseDocService;
import org.hefan.hrm.util.AggsVo;
import org.hefan.hrm.util.AjaxResult;
import org.hefan.hrm.util.PageList;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.elasticsearch.core.ElasticsearchTemplate;
import org.springframework.data.elasticsearch.core.aggregation.AggregatedPage;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.List;
import java.util.stream.Collectors;

@Service
public class CourseDocServiceImpl implements ICourseDocService {

    @Autowired
    private CourseDocRepository repository;

    @Autowired
    private ElasticsearchTemplate template;

    @Autowired
    private HighlightResultMapper highlightResultMapper;

    @Override
    public AjaxResult batchAdd(List<CourseDoc> courseDocs) {
        repository.saveAll(courseDocs);
        return AjaxResult.me();
    }

    @Override
    public AjaxResult batchDel(List<Long> ids) {
        Iterable<CourseDoc> allById = repository.findAllById(ids);
        repository.deleteAll(allById);
        return AjaxResult.me();
    }

    @Override
    public PageList<CourseDoc> queryPageData(CourseDocQuery query) {

        //1 创建构建器
        NativeSearchQueryBuilder builder = new NativeSearchQueryBuilder();

        //2 设置查询条件
        BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();
        String keyword = query.getKeyword();
        //2.1 dsl查询
        if (!StringUtils.isEmpty(keyword)) {
            boolQuery.must(QueryBuilders.multiMatchQuery(keyword, "name","forUser","gradeName","tenantName","courseTypeName"));
        }
        //2.2 dsl过滤  类型 机构 minprie maxprice
        Long courseTypeId = query.getCourseTypeId();
        if (courseTypeId != null) {
            boolQuery.filter(QueryBuilders.termQuery("courseTypeId", courseTypeId));
        }
        Long tenantId = query.getTenantId();
        if (tenantId != null) {
            boolQuery.filter(QueryBuilders.termQuery("tenantId", tenantId));
        }
        Integer priceMin = query.getPriceMin();
        Integer priceMax = query.getPriceMax();
        if (priceMin != null && priceMax != null) {
            boolQuery.filter(QueryBuilders.rangeQuery("price").gte(priceMin).lte(priceMax));
        }
        builder.withQuery(boolQuery);

        //3 排序
        String sortField = query.getSortField();
        String sortFieldName = "price"; // 默认按照价格排序
        switch (sortField.toLowerCase()) {
            case "xl":
                sortFieldName = "saleCount";
                break;
            case "xp":
                sortFieldName = "onlineTime";
                break;
            case "pl":
                sortFieldName = "commentCount";
                break;
            case "rq":
                sortFieldName = "viewCount";
                break;
        }
        SortOrder defaultSortOrder = SortOrder.DESC; // 默认降序
        if (!query.getSortType().equals("desc")) {
            defaultSortOrder = SortOrder.ASC;
        }
        builder.withSort(SortBuilders.fieldSort(sortFieldName).order(defaultSortOrder));

        //4 分页
        builder.withPageable(PageRequest.of(query.getPage() - 1, query.getRows()));

        //5 高亮查询
        HighlightBuilder.Field field = new HighlightBuilder.Field("name")
                .preTags("<b style='color:red'>")
                .postTags("</b>");
        builder.withHighlightFields(field);

        //6 聚合处理
        builder.addAggregation(AggregationBuilders.terms("tenantNameAggs").field("tenantName.keyword").size(20));
        builder.addAggregation(AggregationBuilders.terms("courseTypeNameAggs").field("courseTypeName.keyword").size(20));

        //7 封装结果
        AggregatedPage<CourseDoc> page = template.queryForPage(builder.build(), CourseDoc.class, highlightResultMapper);
        HashMap<String, List<AggsVo>> aggs = new HashMap<>();
        StringTerms tenantNameAggs = (StringTerms) page.getAggregation("tenantNameAggs");
        List<AggsVo> tenantNameAggsVos = getAggsVos(tenantNameAggs);
        aggs.put("tenantNameAggs", tenantNameAggsVos);
        StringTerms courseTypeNameAggs = (StringTerms) page.getAggregation("courseTypeNameAggs");
        List<AggsVo> courseTypeNameAggsVos = getAggsVos(courseTypeNameAggs);
        aggs.put("courseTypeNameAggs", courseTypeNameAggsVos);

        if (page.getTotalElements() == 0) {
            return new PageList<>();
        } else {
            PageList<CourseDoc> pageList = new PageList<>(page.getTotalElements(), page.getContent());
            pageList.setAggsVoData(aggs);
            return pageList;
        }
    }

    private List<AggsVo> getAggsVos(StringTerms terms) {
        List<StringTerms.Bucket> buckets = terms.getBuckets();
        List<AggsVo> aggsVos = buckets.stream().map(bucket -> {
            AggsVo aggsVo = new AggsVo();
            String name = bucket.getKeyAsString();
            long count = bucket.getDocCount();
            aggsVo.setName(name);
            aggsVo.setCount(count);
            return aggsVo;
        }).collect(Collectors.toList());

        return aggsVos;
    }
}
